
const fs = require('fs');
const { Readable } = require('stream');
const ffmpeg = require('fluent-ffmpeg');
const ffmpegPath = require('ffmpeg-static');

class FFmpegStreamReadable extends Readable {
    constructor(opt) {
        super(opt);
    }
    _read() { }
}

module.exports = class Ffmpeg extends EventEmitter {
    addMode = null; // single / batch
    inputStream;
    options = {
        output: '',
        decode: false,
    };

    constructor(output, options) {
        this.options = options;
    }

    init() {
        if (this.inputStream) {
            return;
        }
        this.inputStream = new FFmpegStreamReadable(null);
        new ffmpeg(this.inputStream)
            .setFfmpegPath(ffmpegPath.replace('app.asar', 'app.asar.unpacked'))
            .videoCodec(this.options.decode ? 'libx264' : 'copy')
            .audioCodec(this.options.decode ? 'acc' : 'copy')
            .format('mp4')
            .save(this.options.output)
            .on('progress', info => {
                this.emit('progress', info);
            })
            .on('error', err => {
                this.emit('error', err);
            })
            .on('end', () => {
                this.emit('end');
            });
    }

    async add(input) {
        if (!this.mode) {
            this.mode = 'single';
        } else if (this.mode !== 'single') {
            console.warn('已开始批量合并，请勿重复添加文件');
            return;
        }
        if (!this.inputStream) {
            this.init();
        }
        let stream = input;
        if (typeof stream === 'string') {
            stream = fs.readFileSync(stream);
        }
        this.inputStream.push(stream);
        while (inputStream._readableState.length > 0) {
            await new Promise(resolve => setTimeout(resolve, 200));
        }
    }

    end() {
        this.inputStream.push(null);
        this.inputStream.close();
    }

    async merge(inputList) {
        if (!this.mode) {
            this.mode = 'batch';
        } else if (this.mode !== 'batch') {
            console.warn('已开始单个媒体添加模式，请使用 add 方法添加单个媒体进行合并');
            return;
        } else {
            console.warn('已使用批量合并，请勿重复合并或创建新实例');
            return;
        }
        this.init();
        const inputStream = this.inputStream;
        for (let i = 0; i < inputList.length; i++) {
            let stream = inputList[i];
            if (typeof stream === 'string') {
                stream = fs.readFileSync(stream);
            }
            inputStream.push(stream);
            while (inputStream._readableState.length > 0) {
                await new Promise(resolve => setTimeout(resolve, 200));
            }
        }
        inputStream.push(null);
        inputStream.close();
    }
}
